#include <iostream>
#include <vector>
#include <string>
#include <pthread.h>
#include <semaphore.h>
using namespace std;

template <class T, size_t N = 5>
class RingQueue
{
private:
    void P(sem_t &sem)
    {
        sem_wait(&sem);
    }
    void V(sem_t &sem)
    {
        sem_post(&sem);
    }

public:
    RingQueue()
        : ringQueue_(N)
    {
        cap_ = N;
        sem_init(&p_sem_, 0, 5);
        sem_init(&c_sem_, 0, 0);
        pthread_mutex_init(&Plock, nullptr);
        pthread_mutex_init(&Clock, nullptr);
    }

    void push(const T &data)
    {
        P(p_sem_);
        pthread_mutex_lock(&Plock);
        ringQueue_[p_index_] = data;
        p_index_++;
        p_index_ %= cap_;
        pthread_mutex_unlock(&Plock);
        V(c_sem_);
    }

    T pop()
    {
        P(c_sem_);
        pthread_mutex_lock(&Clock);
        T data = ringQueue_[c_index_];
        c_index_++;
        c_index_ %= cap_;
        pthread_mutex_unlock(&Clock);
        V(p_sem_);
        return data;
    }

    ~RingQueue()
    {
        pthread_mutex_destroy(&Plock);
        pthread_mutex_destroy(&Clock);
        sem_destroy(&p_sem_);
        sem_destroy(&c_sem_);
    }

private:
    vector<T> ringQueue_;
    size_t cap_; // rq capacity

    // 临界资源
    size_t p_index_;
    size_t c_index_;

    // sem
    sem_t p_sem_;
    sem_t c_sem_;

    // mutex 多线程需要
    pthread_mutex_t Plock;
    pthread_mutex_t Clock;
};